import { configByID, gameConfig, gameConfigHandle, propName } from "js/config/gameConfig"
import { GameRouteData, localApi } from "js/core/localApi"
import utils from "js/core/utils"
import bagHandle from "js/handle/bagHandle"
import equipmentHandle from "js/handle/equipmentHandle"
import fighterHandle from "js/handle/fighterHandle"
import partnerHandle from "js/handle/partnerHandle"
import playerHandle from "js/handle/playerHandle"
import treasureHandle from "js/handle/treasureHandle"
import { PosAttriLvlModel } from "js/model/formationModel"
import { ItemModel } from "js/model/itemModel"
import { PartnerModel } from "js/model/partnerModel"
import { HangUpInfo } from "js/model/playerModel"
import { AlchemyType, BagType, MapType, TownBuildType, TownEventType } from "js/typeDefine/typeDefine"

class PlayerRoute {

    @localApi('playerRoute')
    savePlayer(gamRouteData?: GameRouteData) {
        let { player, time, dayTime, random, } = gamRouteData
        return { err: 0 }
    }


    @localApi('playerRoute')
    saveTime(gamRouteData?: GameRouteData) {
        let { player, time, dayTime, random, } = gamRouteData
        player.baseInfo.saveTime = time
        let totalPower = 0
        player.teamList.list.filter(p => p != null).forEach(p => {
            if (p) {
                let fighter = partnerHandle.createPartnerFighter(player, p, false)
                totalPower += fighter.power
            }  
        })
        player.totalPower = totalPower
        return { err: 0 }
    }

    @localApi('playerRoute')
    setMainTip(gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        player.baseInfo.mainTip = true
        return { err: 0 }

    }

    @localApi('playerRoute')
    setSweepTip(gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        player.baseInfo.sweepTip = true
        return { err: 0 }

    }

    @localApi('playerRoute')
    setDisableAutoMap(gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        player.baseInfo.disableAutoMap = !player.baseInfo.disableAutoMap
        return { err: 0 }

    }

    @localApi('playerRoute')
    createPartnerByRole(tid, quality, gamRouteData?: GameRouteData) {
        let { player, random } = gamRouteData
        let index = player.teamList.list.findIndex(p => p == null)
        let campIndex = (player.teamList.camp || []).findIndex(p => p == null)
        if (index == -1) {
            if (campIndex == -1) {
                return { err: 1 }
            }
        }
        let partnerConfig = gameConfigHandle.configByID[tid]
        if (!partnerConfig) {
            return { err: 2 }
        }

        let partner = new PartnerModel({ tID: tid, name: partnerConfig.name, quality })
        partner.index = utils.randomString(16)
        let pos = 0
        let emptyArr = new Array(12).fill(1).map(i => pos++)
        player.teamList.list.forEach((p, i) => {
            if (p) {
                emptyArr[p.formationPos] = null
            }
        })
        emptyArr = emptyArr.filter(i => i != null)
        partner.formationPos = emptyArr.length > 1 ? emptyArr[1] : emptyArr[0]
        partner.fighter = partnerHandle.createPartnerFighter(player, partner)
        if (index == -1) {
            player.teamList.camp[campIndex] = partner
        } else {
            player.teamList.list[index] = partner
        }
        return { err: 0 }
    }

    @localApi('playerRoute')
    diamondCreatePartner(barIndex, quality, attriPoint: any, refreshTimes: number = 1, gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        let needDiamond = refreshTimes * gameConfig.partner.recuritNeedDiamond || 5
        needDiamond = needDiamond > 200 ? 200 : needDiamond
        if (player.itemInfo.diamond < needDiamond) {
            return {
                err: 5
            }
        }
        let barTeam = player.barTeamList
        let barPartner = barTeam[barIndex]
        if (!barPartner) {
            return { err: 2 }
        }
        let partnerConfig = gameConfigHandle.configByID[barPartner.tid]
        let unlockPos = partnerHandle.getUnlockTeamPos(player)
        let index = player.teamList.list.findIndex((p, i) => !p && unlockPos.findIndex(up => up == i) != -1)
        if (player.teamList.camp.length < 50) {
            let newCampList = new Array(50).fill(null)
            for (let i = 0; i < player.teamList.camp.length; i++) {
                newCampList[i] = player.teamList.camp[i]
            }
            player.teamList.camp = newCampList
        }
        let campIndex = (player.teamList.camp || []).findIndex(p => !p)
        if (index == -1) {
            if (campIndex == -1) {
                return { err: 1 }
            }
        }

        if (index != -1) {
            let count = 0
            player.teamList.list.forEach(p => {
                if (p && p.tID == barPartner.tid) {
                    count += 1
                }
            })
            if (count >= 2 && campIndex == -1) {
                return { err: 3 }
            } else if (count >= 2) {
                index = -1
            }
        }
        if (!partnerConfig) {
            return { err: 2 }
        }
        let partner = new PartnerModel({ tID: barPartner.tid, name: partnerConfig.name, quality, attriPoint })
        partner.index = utils.randomString(16)
        if (index == -1) {
            partner.fighter = partnerHandle.createPartnerFighter(player, partner)
            player.teamList.camp[campIndex] = partner
        } else {
            let pos = 0
            let emptyArr = new Array(12).fill(1).map(i => pos++)
            player.teamList.list.forEach((p, i) => {
                if (p) {
                    emptyArr[p.formationPos] = null
                }
            })
            emptyArr = emptyArr.filter(i => i != null)
            partner.formationPos = emptyArr[0]
            partner.fighter = partnerHandle.createPartnerFighter(player, partner)
            player.teamList.list[index] = partner
        }
        player.baseInfo.barRecuritTimes += 1
        if (!player.baseInfo.barRecuritTimes1) {
            player.baseInfo.barRecuritTimes1 = 0
        }
        player.baseInfo.barRecuritTimes1 += 1
        player.itemInfo.diamond -= needDiamond
        player.itemInfo.usedItemStat['diamond'] = (player.itemInfo.usedItemStat['diamond'] || 0) + needDiamond
        player.barTeamList[barIndex] = null
        playerHandle.initTeam(player)
        return { err: 0 }
    }

    @localApi('playerRoute')
    createPartner(barIndex, quality, attriPoint: any, gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        let barTeam = player.barTeamList
        let barPartner = barTeam[barIndex]
        if (!barPartner) {
            return { err: 2 }
        }
        let partnerConfig = gameConfigHandle.configByID[barPartner.tid]
        let index = player.teamList.list.findIndex(p => !p)
        let campIndex = (player.teamList.camp || []).findIndex(p => !p)
        if (index == -1) {
            if (campIndex == -1) {
                return { err: 1 }
            }
        }
        // let limitConfig = gameConfig.partner.posLimit[index]
        // let isLimit = gameUtils.isLimit(player, limitConfig[0], limitConfig[1])
        // if (isLimit) {
        //     return {
        //         err: 4
        //     }
        // }
        if (!partnerConfig) {
            return { err: 2 }
        }
        // let count = 0
        // player.teamList.list.forEach(p => {
        //     if (p && p.tID == barPartner.id) {
        //         count += 1
        //     }
        // })
        // if (count >= 2) {
        //     return { err: 3 }
        // }
        let partner = new PartnerModel({ tID: barPartner.tid, name: partnerConfig.name, quality, attriPoint })
        partner.index = utils.randomString(16)
        if (index == -1) {
            partner.fighter = partnerHandle.createPartnerFighter(player, partner)
            player.teamList.camp[campIndex] = partner
        } else {
            let pos = 0
            let emptyArr = new Array(12).fill(1).map(i => pos++)
            player.teamList.list.forEach((p, i) => {
                if (p) {
                    emptyArr[p.formationPos] = null
                }
            })
            emptyArr = emptyArr.filter(i => i != null)
            partner.formationPos = emptyArr[0]
            partner.fighter = partnerHandle.createPartnerFighter(player, partner)
            player.teamList.list[index] = partner
        }
        player.baseInfo.barRecuritTimes += 1
        player.barTeamList[barIndex] = null
        playerHandle.initTeam(player)
        return { err: 0 }
    }

    @localApi('playerRoute')
    updatePartnerPos(first: number, next: number, gamRouteData?: GameRouteData) {
        let { player, time, dayTime, random, } = gamRouteData
        let teamList = player.teamList.list
        let firstPartner = teamList.find(p => p && p.formationPos == first)
        let nextPartner = teamList.find(p => p && p.formationPos == next)
        if (firstPartner) {
            firstPartner.formationPos = next
        }
        if (nextPartner) {
            nextPartner.formationPos = first
        }
        playerHandle.initTeam(player)
        return { err: 0 }
    }

    @localApi('playerRoute')
    checkTeamPos(gamRouteData?: GameRouteData) {
        // let { player, time, dayTime, random, } = gamRouteData
        // let pos = 0
        // let emptyArr = new Array(12).fill(pos++)
        // player.teamList.list.forEach(p => {
        //     if (p) {
        //         emptyArr = emptyArr.map(ea => ea != p)
        //     }
        // })
        // let idx = 0
        // player.teamList.list.forEach(p => {
        //     if (p) {
        //         p.formationPos = emptyArr[idx++]
        //     }
        // })
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    setAnimationType(type: number, gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        player.baseInfo.animationType = type
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    setMenuNew(menuText: string, gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        let menu = player.info['menu']
        if (!menu) {
            menu = {}
        }
        menu[menuText] = false
        player.info['menu'] = menu
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    autoAll(gamRouteData?: GameRouteData) {
        // 奇遇
        let { player, random, time, dayTime } = gamRouteData
        let rate = gameConfig.map.wbTriggeRate
        let num = random.intn(100)
        let todayTimes = player.wbInfo.todayTimes || 0
        let alchemyConfig: any = Object.entries(gameConfig.alchemy).find(a => {
            let config: any = a[1]
            return config.aType == AlchemyType.WorldBoss
        })
        let lvl = player.alchemyInfo.lvls[alchemyConfig[0]] || 0
        let addTimes = lvl ? utils.getIncValue(alchemyConfig[1].values, lvl) : 0
        if (playerHandle.isMember(player, time)) {
            addTimes += gameConfig.vip.wbTimesOfAfd
        }

        if (player.baseInfo.longVip) {
            addTimes += gameConfig.vip.wbTimesOfLongVip
        }

        if (num <= rate && player.wbInfo.expireTime < time && todayTimes < (gameConfig.map.wbMaxTimes + addTimes)) {
            player.wbInfo.expireTime = time + gameConfig.map.wbExpireTime
            player.wbInfo.times = 0
        }

        // 重置
        if (player.baseInfo.dayTime !== dayTime) {
            player.baseInfo.dayTime = dayTime
            playerHandle.resetDay(player, random)
        }
        // 建造时间查询
        let newBuildStatus = {}
        Object.entries(player.townInfo.buildStatus).forEach(b => {
            let type: any = b[0]
            let completeTime: any = b[1] || null
            if (completeTime && completeTime <= time) {
                if (type == TownBuildType.Town) {
                    player.townInfo.lvl += 1
                    let boomingValues = gameConfig.town.list[0].boomingValues
                    player.townInfo.booming = (player.townInfo.booming || 0) + utils.getIncValue(boomingValues, player.townInfo.lvl)
                } else {
                    player.townInfo.subBuildLvl[type] = (player.townInfo.subBuildLvl[type] || 0) + 1
                    let boomingValues = gameConfig.town.list.find(l => l.kind == type).boomingValues
                    player.townInfo.booming = (player.townInfo.booming || 0) + utils.getIncValue(boomingValues, player.townInfo.subBuildLvl[type])
                }
            } else {
                newBuildStatus[type] = completeTime
            }
        })
        player.townInfo.buildStatus = newBuildStatus
        // 安定值下降查询
        let decrScoreTimes = player.townInfo.decrScoreTimes || time
        if (time - decrScoreTimes > gameConfig.town.reduceSaveScoreTimes) {
            let times = Math.floor((time - decrScoreTimes) / gameConfig.town.reduceSaveScoreTimes)
            player.townInfo.saveScore -= utils.getIncValue(gameConfig.town.reduceSaveScoreValues, times)
            if (player.townInfo.saveScore <= 0) {
                player.townInfo.saveScore = 0
            } else if (player.townInfo.saveScore > 100) {
                player.townInfo.saveScore = 100
            }
            decrScoreTimes = decrScoreTimes + (times * gameConfig.town.reduceSaveScoreTimes)
        }
        player.townInfo.decrScoreTimes = decrScoreTimes
        player.treasureInfo.treasurePower = 1
        // 完成任务
        player.townInfo.taskList.filter(t => t.status == 1).forEach(t => {
            if (t.completeTime <= time) {
                t.status = 2
                player.townInfo.saveScore += (t.saveScore || 0)
                if (player.townInfo.saveScore > 100) {
                    player.townInfo.saveScore = 100
                }

                let reard = t.reward
                if (reard.itemID == 'treasure') {
                    if (t.result) {
                        bagHandle.AddItemComponent(player.treasureBag, reard.value)
                    }
                } else if (reard.itemID == 'exp') {
                    let coe = t.result ? 1 : -1
                    player.teamList.list.forEach(p => {
                        if (p) {
                            p.exp += ((reard.value || 0) * coe)
                            if (p.exp < 0) {
                                p.exp = 0
                            }
                        }
                    })
                } else if (reard.itemID == 'gold') {
                    let coe = t.result ? 1 : -1
                    player.itemInfo.gold += (t.value || 0) * coe
                    if (player.itemInfo.gold < 0) {
                        player.itemInfo.gold = 0
                    }
                } else if (reard.itemID == 'diamond') {
                    let coe = t.result ? 1 : -1
                    player.itemInfo.diamond += (t.value || 0) * coe
                    if (player.itemInfo.diamond < 0) {
                        player.itemInfo.diamond = 0
                    }
                } else if (typeof reard.itemID == 'number') {
                    if (t.result) {
                        bagHandle.AddItem(player.bag, reard.itemID, reard.value, random)
                    }
                }
            }
        })
        // 称号
        playerHandle.getPlayerTitles(null, time, player)

        // 炼金
        let buildInfo = player.alchemyInfo.build
        let entries = Object.entries(buildInfo)
        for (let i = 0; i < entries.length; i++) {
            let entry = entries[i];
            let id = entry[0]
            let completeTime: any = entry[1]
            if (completeTime <= time) {
                delete player.alchemyInfo.build[id]
                player.alchemyInfo.lvls[id] = (player.alchemyInfo.lvls[id] || 0) + 1
            }
        }
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    triggeWb(gamRouteData?: GameRouteData) {
        let { player, random, time } = gamRouteData
        let rate = gameConfig.map.wbTriggeRate
        let num = random.intn(100)
        let todayTimes = player.wbInfo.todayTimes || 0
        let alchemyConfig: any = Object.entries(gameConfig.alchemy).find(a => {
            let config: any = a[1]
            return config.aType == AlchemyType.WorldBoss
        })
        let lvl = player.alchemyInfo.lvls[alchemyConfig[0]] || 0
        let addTimes = lvl ? utils.getIncValue(alchemyConfig[1].values, lvl) : 0
        if (playerHandle.isMember(player, time)) {
            addTimes += gameConfig.vip.wbTimesOfAfd
        }
        if (num <= rate && player.wbInfo.expireTime < time && todayTimes < (gameConfig.map.wbMaxTimes + addTimes)) {
            player.wbInfo.expireTime = time + gameConfig.map.wbExpireTime
            player.wbInfo.times = 0
            return {
                err: 0
            }
        } else {
            return {
                err: 100
            }
        }
    }

    @localApi('playerRoute')
    switchGameSet(key, gamRouteData?: GameRouteData) {
        let { player, random, time } = gamRouteData
        player.gameSet[key] = !player.gameSet[key]
        return {
            err: 0,
            data: player.gameSet[key]
        }
    }

    @localApi('playerRoute')
    bagArrange(bagType: BagType, gameRouteData?: GameRouteData) {
        let { player } = gameRouteData
        bagHandle.arrange(player, bagType)
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    reset(gameRouteData?: GameRouteData) {
        let { player } = gameRouteData
        player.adventureInfo.mapID = 100001
        player.adventureInfo.floor = 4
        player.adventureInfo.totalFloor = 4
        player.baseInfo.mapProgressMax = 1000413448573
        player.deepInfo.nightProgress = 0
        player.deepInfo.progress = 0
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    refreshTownTask(gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        playerHandle.resetTownTask(player, random)
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    townLvlUp(gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        if (player.townInfo.buildStatus[TownBuildType.Town] != null) {
            return {
                err: 5
            }
        }
        if (player.townInfo.lvl >= gameConfig.town.townMaxLvl) {
            return {
                err: 6
            }
        }
        let needConfig = gameConfig.town.list[0].lvlUpNeed
        let lvl = player.townInfo.lvl + 1
        let preLvl = needConfig.preLvl[lvl] || {}
        let unBuildData = {}, allPreBuild = true
        Object.entries(preLvl).forEach(pre => {
            let buildType = pre[0]
            let preBuildLvl = pre[1]
            if (!player.townInfo.subBuildLvl[buildType] || player.townInfo.subBuildLvl[buildType] < preBuildLvl) {
                unBuildData[buildType] = preBuildLvl
                allPreBuild = false
            }
        })
        if (!allPreBuild) {
            return {
                err: 7,
                data: unBuildData
            }
        }
        let res = playerHandle.getNeedAndUse(player, needConfig, lvl)
        if (res) {
            return {
                err: res
            }
        }
        let needTimes = gameConfig.town.list[0].buildTime
        let completeTime = time + utils.getIncValue(needTimes, lvl)
        player.townInfo.buildStatus[TownBuildType.Town] = completeTime
        return {
            err: 0,
            data: {
                completeTime
            }
        }
    }

    @localApi('playerRoute')
    townSubBuildLvlUp(type: TownBuildType, gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        if (player.townInfo.buildStatus[type] != null) {
            return {
                err: 5
            }
        }
        let buildConfig = gameConfig.town.list.find(l => l.kind == type)
        let oLvl = (player.townInfo.subBuildLvl[type] || 0)
        if (oLvl >= gameConfig.town.maxLvl) {
            return {
                err: 6
            }
        }
        let needConfig = buildConfig.lvlUpNeed
        let lvl = oLvl + 1
        let preLvl = needConfig.preLvl[lvl] || {}
        let unBuildData = {}, allPreBuild = true
        Object.entries(preLvl).forEach(pre => {
            let buildType: any = pre[0]
            let preBuildLvl: any = pre[1]
            if (buildType == TownBuildType.Town && player.townInfo.lvl < preBuildLvl) {
                unBuildData[buildType] = preBuildLvl
                allPreBuild = false
            } else if (buildType != TownBuildType.Town && (!player.townInfo.subBuildLvl[buildType] || player.townInfo.subBuildLvl[buildType] < preBuildLvl)) {
                unBuildData[buildType] = preBuildLvl
                allPreBuild = false
            }
        })
        if (!allPreBuild) {
            return {
                err: 7,
                data: unBuildData
            }
        }
        let res = playerHandle.getNeedAndUse(player, needConfig, lvl)
        if (res) {
            return {
                err: res
            }
        }
        let needTimes = buildConfig.buildTime
        let completeTime = time + utils.getIncValue(needTimes, lvl)
        player.townInfo.buildStatus[type] = completeTime
        return {
            err: 0,
            data: {
                completeTime
            }
        }
    }

    @localApi('playerRoute')
    autoTown(gameRouteData?: GameRouteData) {
        let { player, time, random, dayTime } = gameRouteData
        // 重置
        if (player.baseInfo.dayTime !== dayTime) {
            player.baseInfo.dayTime = dayTime
            playerHandle.resetDay(player, random)
        }
        // 建造时间查询
        let newBuildStatus = {}
        Object.entries(player.townInfo.buildStatus).forEach(b => {
            let type: any = b[0]
            let completeTime: any = b[1] || null
            if (completeTime && completeTime <= time) {
                if (type == TownBuildType.Town) {
                    player.townInfo.lvl += 1
                    let boomingValues = gameConfig.town.list[0].boomingValues
                    player.townInfo.booming = (player.townInfo.booming || 0) + utils.getIncValue(boomingValues, player.townInfo.lvl)
                } else {
                    player.townInfo.subBuildLvl[type] = (player.townInfo.subBuildLvl[type] || 0) + 1
                    let boomingValues = gameConfig.town.list.find(l => l.kind == type).boomingValues
                    player.townInfo.booming = (player.townInfo.booming || 0) + utils.getIncValue(boomingValues, player.townInfo.subBuildLvl[type])
                }
            } else {
                newBuildStatus[type] = completeTime
            }
        })
        player.townInfo.buildStatus = newBuildStatus
        // 安定值下降查询
        let decrScoreTimes = player.townInfo.decrScoreTimes || time
        if (time - decrScoreTimes > gameConfig.town.reduceSaveScoreTimes) {
            let times = Math.floor((time - decrScoreTimes) / gameConfig.town.reduceSaveScoreTimes)
            player.townInfo.saveScore -= utils.getIncValue(gameConfig.town.reduceSaveScoreValues, times)
            if (player.townInfo.saveScore <= 0) {
                player.townInfo.saveScore = 0
            } else if (player.townInfo.saveScore > 120) {
                player.townInfo.saveScore = 120
            }
            decrScoreTimes = decrScoreTimes + (times * gameConfig.town.reduceSaveScoreTimes)
        }
        player.townInfo.decrScoreTimes = decrScoreTimes
        player.treasureInfo.treasurePower = 1
        // 完成任务
        player.townInfo.taskList.filter(t => t.status == 1).forEach(t => {
            if (t.completeTime <= time) {
                t.status = 2
                player.townInfo.saveScore += (t.saveScore || 0)
                if (player.townInfo.saveScore > 120) {
                    player.townInfo.saveScore = 120
                }

                let reard = t.reward
                if (reard.itemID == 'treasure') {
                    if (t.result) {
                        bagHandle.AddItemComponent(player.treasureBag, reard.value)
                    }
                } else if (reard.itemID == 'exp') {
                    let coe = t.result ? 1 : -1
                    player.teamList.list.forEach(p => {
                        if (p) {
                            p.exp += ((reard.value || 0) * coe)
                            if (p.exp < 0) {
                                p.exp = 0
                            }
                        }
                    })
                } else if (reard.itemID == 'gold') {
                    let coe = t.result ? 1 : -1
                    player.itemInfo.gold += (t.value || 0) * coe
                    if (player.itemInfo.gold < 0) {
                        player.itemInfo.gold = 0
                    }
                } else if (reard.itemID == 'diamond') {
                    let coe = t.result ? 1 : -1
                    player.itemInfo.diamond += (t.value || 0) * coe
                    if (player.itemInfo.diamond < 0) {
                        player.itemInfo.diamond = 0
                    }
                } else if (typeof reard.itemID == 'number') {
                    if (t.result) {
                        bagHandle.AddItem(player.bag, reard.itemID, reard.value, random)
                    }
                }
            }
        })
        // 称号
        playerHandle.getPlayerTitles(null, time, player)
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    refreshTownTask2(gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        if (player.townInfo.saveScore < 90) {
            playerHandle.resetTownTask2(player, random)
        }
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    doTownTask(index, gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        let existsTask = player.townInfo.taskList.find(t => t.status == 1)
        if (existsTask) {
            return {
                err: 1
            }
        }
        existsTask = player.townInfo.taskList.find((t, i) => t.status == 2 && i == index)
        if (existsTask) {
            return {
                err: 2
            }
        }
        let task = player.townInfo.taskList[index]
        task.status = 1
        let completeTime = utils.getIncValue(task.timeConfig, player.townInfo.lvl)
        task.completeTime = time + completeTime
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    getTownSearchTask(gameRouteData?: GameRouteData) {
        let { player, time, random } = gameRouteData
        let maxTimes = gameConfig.town.eventFreeTimes
        if (player.baseInfo.longVip) {
            maxTimes = gameConfig.town.eventMaxTimes
        } else if (playerHandle.isMember(player, time)) {
            maxTimes = maxTimes + gameConfig.vip.townSearchAddOfAfd
        }
        let searchTaskList = player.townInfo.searchTaskList
        if (!searchTaskList) {
            searchTaskList = []
            player.townInfo.searchTaskList = searchTaskList
        }
        if (searchTaskList.length >= maxTimes) {
            return {
                err: 1
            }
        }
        let addTask = playerHandle.createTownSearchTask(player, false, time, random)
        let newTaskList = []
        addTask.forEach(at => {
            let task = { done: false, data: at }
            newTaskList.push(task)
        })
        newTaskList.forEach(nt => {
            player.townInfo.searchTaskList.push(nt)
        })
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    doSearch(id, isUseItem: boolean, gameRouteData?: GameRouteData) {
        let { player, time, dayTime, random } = gameRouteData
        let searchTaskList = player.townInfo.searchTaskList
        if (!searchTaskList) {
            searchTaskList = []
            player.townInfo.searchTaskList = searchTaskList
        }

        let unDone = searchTaskList.find(t => t.done == false)
        if (!unDone) {
            let maxTimes = gameConfig.town.eventFreeTimes
            if (player.baseInfo.longVip) {
                maxTimes = gameConfig.town.eventMaxTimes
            } else if (playerHandle.isMember(player, time)) {
                maxTimes = maxTimes + gameConfig.vip.townSearchAddOfAfd
            }
            let searchTaskList = player.townInfo.searchTaskList
            if (searchTaskList.length >= maxTimes) {
                return {
                    err: 1
                }
            }
            if (isUseItem) {
                let res = playerHandle.getNeedAndUse(player, gameConfig.town.eventItemUse, 1)
                if (res) {
                    return {
                        err: res
                    }
                }
            }
            let addTask = playerHandle.createTownSearchTask(player, isUseItem, time, random)
            let newTaskList = []
            addTask.forEach(at => {
                let task = { done: false, data: at, isUseItem }
                newTaskList.push(task)
            })
            newTaskList.forEach(nt => {
                player.townInfo.searchTaskList.push(nt)
            })
            unDone = player.townInfo.searchTaskList.find(t => t.done == false)
        }
        if (unDone) {
            let searchTimes = player.townInfo.searchTimes || 0
            player.townInfo.searchTimes = searchTimes + 1
            //
            let lvl = player.townInfo.subBuildLvl[TownBuildType.Task] || 0
            let data = unDone.data
            unDone.done = true
            if (data.eventType == TownEventType.Punish) {
                if (data.townLvl != null) {
                    player.townInfo.lvl -= data.townLvl
                    if (player.townInfo.lvl < 0) {
                        player.townInfo.lvl = 0
                    }
                } else {
                    let mapComfig = gameConfigHandle.configByID[player.adventureInfo.mapID]
                    if (data.reward.resourceItems) {
                        let get: any
                        if (data.reward.random) {
                            get = utils.getOneFromArray(data.reward.resourceItems, random)
                        } else {
                            get = data.reward.resourceItems[0]
                        }
                        if (get.itemID == 'gold') {
                            let amount = (utils.getIncValue(get.amount, lvl) || 0) * utils.getIncValue(gameConfig.map.getGold, mapComfig.mapLvl || 1)
                            player.itemInfo.gold -= amount
                            if (player.itemInfo.gold < 0) {
                                player.itemInfo.gold = 0
                            }
                            unDone.value1 = 'gold'
                            unDone.values = amount
                        } else if (typeof get.itemID == "number") {
                            let amount = utils.getIncValue(get.amount, lvl) || 0
                            amount = amount * (utils.getIncValue(gameConfig.map.getResource, mapComfig.mapLvl) || 1)
                            bagHandle.removeItemByItemId(player.bag, get.itemID, amount)
                            unDone.value1 = propName[get.itemID]
                            unDone.values = amount
                        } else if (get.itemID == "exp") {
                            let amount = utils.getIncValue(get.amount, lvl) || 0
                            amount = amount * (utils.getIncValue(gameConfig.map.getExp, mapComfig.mapLvl) || 1)
                            player.teamList.list.forEach(p => {
                                if (p) {
                                    p.exp -= amount
                                    if (p.exp < 0) {
                                        p.exp = 0
                                    }
                                }
                            })
                            unDone.value1 = 'exp'
                            unDone.values = amount
                        }
                    } else if (data.reward.items) {
                        let get: any
                        if (data.reward.random) {
                            get = utils.getOneFromArray(data.reward.items, random)
                        } else {
                            get = data.reward.items[0]
                        }
                        if (get.itemID == 'gold') {
                            let amount = (utils.getIncValue(get.amount, lvl) || 0)
                            player.itemInfo.gold -= amount
                            if (player.itemInfo.gold < 0) {
                                player.itemInfo.gold = 0
                            }
                            unDone.value1 = 'gold'
                            unDone.values = amount
                        } else if (typeof get.itemID == "number") {
                            let amount = utils.getIncValue(get.amount, lvl) || 0
                            amount = amount * (utils.getIncValue(gameConfig.map.getResource, mapComfig.mapLvl) || 1)
                            bagHandle.removeItemByItemId(player.bag, get.itemID, amount)
                            unDone.value1 = propName[get.itemID]
                            unDone.values = amount
                        } else if (get.itemID == "exp") {
                            let amount = utils.getIncValue(get.amount, lvl) || 0
                            player.teamList.list.forEach(p => {
                                if (p) {
                                    p.exp -= amount
                                    if (p.exp < 0) {
                                        p.exp = 0
                                    }
                                }
                            })
                            unDone.value1 = 'exp'
                            unDone.values = amount
                        }
                    }
                }
            } else {
                let mapComfig = gameConfigHandle.configByID[player.adventureInfo.mapID]
                if (data.reward.resourceItems) {
                    let get: any
                    if (data.reward.random) {
                        get = utils.getOneFromArray(data.reward.resourceItems, random)
                    } else {
                        get = data.reward.resourceItems[0]
                    }
                    if (get.itemID == 'gold') {
                        let amount = (utils.getIncValue(get.amount, lvl) || 0) * utils.getIncValue(gameConfig.map.getGold, mapComfig.mapLvl || 1)
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        player.itemInfo.gold += amount
                        unDone.value1 = 'gold'
                        unDone.values = amount
                    } else if (typeof get.itemID == "number") {
                        let amount = utils.getIncValue(get.amount, lvl) || 0
                        amount = amount * (utils.getIncValue(gameConfig.map.getResource, mapComfig.mapLvl) || 1)
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        bagHandle.AddItem(player.bag, get.itemID, amount, random)
                        unDone.value1 = propName[get.itemID]
                        unDone.values = amount
                    } else if (get.itemID == "exp") {
                        let amount = utils.getIncValue(get.amount, lvl) || 0
                        amount = amount * (utils.getIncValue(gameConfig.map.getExp, mapComfig.mapLvl) || 1)
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        player.teamList.list.forEach(p => {
                            if (p) {
                                p.exp += amount
                            }
                        })
                        unDone.value1 = 'exp'
                        unDone.values = amount
                    }
                } else if (data.reward.items) {
                    let get: any
                    if (data.reward.random) {
                        get = utils.getOneFromArray(data.reward.items, random)
                    } else {
                        get = data.reward.items[0]
                    }
                    if (get.itemID == 'gold') {
                        let amount = (utils.getIncValue(get.amount, lvl) || 0)
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        player.itemInfo.gold += amount
                        unDone.value1 = 'gold'
                        unDone.values = amount
                    } else if (get.itemID == 'diamond') {
                        let amount = (utils.getIncValue(get.amount, lvl) || 0)
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        player.itemInfo.diamond += amount
                        unDone.value1 = 'diamond'
                        unDone.values = amount
                    } else if (typeof get.itemID == "number") {
                        let amount = utils.getIncValue(get.amount, lvl) || 0
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        bagHandle.AddItem(player.bag, get.itemID, amount, random)
                        unDone.value1 = propName[get.itemID]
                        unDone.values = amount
                    } else if (get.itemID == "treasure") {
                        let tid: any = utils.getOneFromArray(data.reward.dropItems, random) || 173001

                        let item = treasureHandle.createTreasure(tid, 1, random, random.intn(5))
                        bagHandle.AddItemComponent(player.treasureBag, item)
                        unDone.value1 = [item.treasure.quality, propName[tid]]
                        unDone.values = 1
                    } else if (get.itemID == "exp") {
                        let amount = utils.getIncValue(get.amount, lvl) || 0
                        if (unDone.isUseItem) {
                            amount += Math.floor(amount * 20 / 100)
                        }
                        player.teamList.list.forEach(p => {
                            if (p) {
                                p.exp += amount
                            }
                        })
                        unDone.value1 = 'exp'
                        unDone.values = amount
                    }
                }
            }
        }
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    getSpringReward(selfReward, data: any, gamRouteData?: GameRouteData) {
        let { player } = gamRouteData
        let diamond = 0
        let springReward = gameConfig.town.springReward
        let signInInfo = player.townInfo.signInInfo || { selfSignIn: false, serverSignIn: false }
        if (selfReward && player.townInfo.lvl) {
            if (signInInfo.selfSignIn) {
                return {
                    err: 1
                }
            }
            let lvl = player.townInfo.lvl
            diamond = springReward.baseDiamond + utils.getIncValue(springReward.baseValues, lvl - 1)
            signInInfo['selfSignIn'] = true
        } else if (!selfReward && player.townInfo.lvl && data) {
            if (signInInfo.serverSignIn) {
                return {
                    err: 1
                }
            }
            diamond = springReward.boomingBaseDiamond
            let addDiamond = 0
            let entries = Object.entries(springReward.boomingThreshold)
            for (let i = 0; i < entries.length; i++) {
                let entry = entries[i];
                let threshold: any = entry[0]
                let diamondForThreshold: any = entry[1]
                if (data.booming >= threshold) {
                    addDiamond = diamondForThreshold
                } else {
                    break
                }
            }
            let per = 100
            entries = Object.entries(springReward.saveScoreThreshold)
            for (let i = 0; i < entries.length; i++) {
                let entry = entries[i];
                let threshold: any = entry[0]
                let diamondForPer: any = entry[1]
                if (data.avgScore >= Number(threshold)) {
                    per = diamondForPer
                } else {
                    break
                }
            }
            diamond += Math.floor(addDiamond * per / 100)
            signInInfo['serverSignIn'] = true
        }
        player.itemInfo.diamond += diamond
        player.townInfo.signInInfo = signInInfo
        return {
            err: 0,
            data: diamond
        }
    }

    @localApi('playerRoute')
    townMake(data, gamRouteData?: GameRouteData) {
        let { player, time, random } = gamRouteData
        let { makeItemLvl, makeItemKind, useItemStatus, baseMake, coe } = data
        let lvl = player.townInfo.subBuildLvl[TownBuildType.Make] || 0
        let item: ItemModel = null
        if (baseMake) {
            if (!lvl) {
                return {
                    err: 5
                }
            }
            let isHasEmpty = bagHandle.IsHasEmpty(player.equipmentBag, 1)
            if (!isHasEmpty) {
                return {
                    err: 6
                }
            }
            let baseMakeNeed = gameConfig.town.makeConfig.baseMakeNeed
            coe = coe || 100
            let res = playerHandle.getNeedAndUse(player, baseMakeNeed, lvl, null, coe)
            if (res) {
                return {
                    err: res
                }
            }
            data.time = time
            item = equipmentHandle.townCreate(player, data, random)
            bagHandle.AddItemComponent(player.equipmentBag, item)
            let makeInfo = player.townInfo.makeInfo || { makeTimes: 0 }
            makeInfo.makeTimes = (makeInfo.makeTimes || 0) + 1
            player.townInfo.makeInfo = makeInfo
        } else {
            if (!lvl) {
                return {
                    err: 5
                }
            }
            let isHasEmpty = bagHandle.IsHasEmpty(player.equipmentBag, 1)
            if (!isHasEmpty) {
                return {
                    err: 6
                }
            }
            let highMakeNeed = gameConfig.town.makeConfig.highMakeNeed
            coe = coe || 100
            let res = playerHandle.getNeedAndUse(player, highMakeNeed, lvl, null, coe)
            if (res) {
                return {
                    err: res
                }
            }
            data.time = time
            item = equipmentHandle.townCreate(player, data, random)
            bagHandle.AddItemComponent(player.equipmentBag, item)
            let makeInfo = player.townInfo.makeInfo || { makeTimes: 0 }
            makeInfo.makeTimes = (makeInfo.makeTimes || 0) + 1
            player.townInfo.makeInfo = makeInfo
        }
        return {
            err: 0,
            data: item
        }
    }

    @localApi('playerRoute')
    townMake2(data, gamRouteData?: GameRouteData) {
        let { player, time, random } = gamRouteData
        let { makeItemLvl, makeItemKind, useItemNum, subItemKind, target, coe } = data
        let lvl = player.townInfo.subBuildLvl[TownBuildType.Make] || 0
        let item: ItemModel = null
        if (!lvl) {
            return {
                err: 5
            }
        }
        let isHasEmpty = bagHandle.IsHasEmpty(player.equipmentBag, 1)
        if (!isHasEmpty) {
            return {
                err: 6
            }
        }
        coe = coe || 100
        let needConfig = gameConfig.town.makeConfig.highMakeNeed
        let items = []
        needConfig.items.forEach(it => {
            items.push(it)
        })
        if (useItemNum) {
            items.push({ itemID: 170009, amount: [0, 0], min: useItemNum })
        }
        let res = playerHandle.getNeedAndUse(player, { items }, lvl, null, coe)
        if (res) {
            return {
                err: res
            }
        }
        data.time = time
        item = equipmentHandle.townCreate2(player, data, random)
        bagHandle.AddItemComponent(player.equipmentBag, item)
        let makeInfo = player.townInfo.makeInfo || { makeTimes: 0 }
        makeInfo.makeTimes = (makeInfo.makeTimes || 0) + 1
        player.townInfo.makeInfo = makeInfo
        return {
            err: 0,
            data: item
        }
    }

    @localApi('playerRoute')
    checkTownTask(gamRouteData?: GameRouteData) {
        let { dayTime, player } = gamRouteData
        // if (dayTime == 1719072000000 && !player.info['resetTownTask1']) {
        //     player.townInfo.searchTaskList = []
        //     player.info['resetTownTask1'] = true
        // }
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    checkPlayerTitle(id, gamRouteData?: GameRouteData) {
        let { time, player } = gamRouteData
        let nowActive = playerHandle.getPlayerTitles(id, time, player)
        if (nowActive) {
            return {
                err: 0,
                data: id
            }
        }
        return {
            err: 1,
        }
    }

    @localApi('playerRoute')
    getWbMapId(gamRouteData?: GameRouteData) {
        let { player, random, time } = gamRouteData
        let mapId = gameConfig.map.wbBaseMapId
        // 版本测试 rate = 5
        let rate = 20
        // if (userData.test) {
        //     rate = 70
        // }
        if (playerHandle.isMember(player, time)) {
            rate += gameConfig.vip.addNewWbRateOfAfd || 0
        }
        let vip = playerHandle.getVipLvl(player)
        if (vip) {
            rate += gameConfig.vip.addNewWbRate[vip] || 0
        }
        let randomRate = random.intn(100)
        if (randomRate < rate) {
            mapId = gameConfig.map.wbNewMapId
        }
        return {
            err: 0,
            data: mapId
        }
    }

    @localApi('playerRoute')
    initPlayer(gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        playerHandle.initPlayer(player, time, dayTime)
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    switchGameMode(gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        let needDiamond = gameConfig.newland.needDiamond
        let res = playerHandle.getNeedAndUse(player, { items: [{ itemID: 'diamond', amount: [needDiamond, 0] }] }, 1)
        if (res) {
            return {
                err: res
            }
        }
        let gameMode = player.gameSet.gameMode
        if (gameMode) {
            if (!player.adventureInfo.hangupInfo) {
                player.adventureInfo.hangupInfo = new HangUpInfo({})
            }
            player.adventureInfo.hangupInfo.hangup = false
            player.adventureInfo.hangupInfo.mapID = null
        }
        player.gameSet.gameMode = !gameMode
        if (!player.equipmentBag2 || player.equipmentBag2.type != BagType.Equipment2) {
            playerHandle.initBag(player)
        }
        playerHandle.initTeam(player)
        return {
            err: 0,
            data: gameMode
        }
    }

    @localApi('playerRoute')
    startNewMap(mapID, gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        let mapConfig = gameConfigHandle.configByID[mapID]
        if (!mapConfig || mapConfig.mapType != MapType.Fantasy) {
            return {
                err: 1
            }
        }
        if (!player.adventureInfo.newMapProgress) {
            player.adventureInfo.newMapProgress = {}
        }
        if (!player.adventureInfo.newMapProgress[mapID] && !mapConfig.initMap) {
            return {
                err: 2
            }
        }

        player.adventureInfo.newMapID = mapID
        player.adventureInfo.newFloor = 1
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    nextNewMap(gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        let mapID = player.adventureInfo.newMapID
        let mapConfig = gameConfigHandle.configByID[mapID]
        if (!mapConfig || mapConfig.mapType != MapType.Fantasy) {
            return {
                err: 1
            }
        }
        if (!player.adventureInfo.newMapProgress[mapID] || player.adventureInfo.newMapProgress[mapID] < 10) {
            return {
                err: 2
            }
        }

        player.adventureInfo.newMapID = mapConfig.nextMapID || mapID
        player.adventureInfo.newFloor = 1
        if (!player.adventureInfo.newMapProgress[mapConfig.nextMapID]) {
            player.adventureInfo.newMapProgress[mapConfig.nextMapID] = 1
        }
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    hangUp(gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        let mapID = player.adventureInfo.newMapID
        let mapConfig = gameConfigHandle.configByID[mapID]
        if (!mapConfig || mapConfig.mapType != MapType.Fantasy) {
            return {
                err: 1
            }
        }
        if (!player.adventureInfo.hangupInfo) {
            player.adventureInfo.hangupInfo = new HangUpInfo({})
        }
        player.adventureInfo.hangupInfo.hangup = true
        player.adventureInfo.hangupInfo.mapID = mapID
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    lvlupPosAttri(attri, gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        if (!player.formation.posAttriLvl) {
            player.formation.posAttriLvl = new PosAttriLvlModel({})
        }
        let attriPosLvl = player.formation.posAttriLvl[attri] || 0
        if (attriPosLvl >= gameConfig.baseFormation.newFormationPosMaxLvl) {
            return {
                err: 5
            }
        }
        let needConfig = gameConfig.baseFormation.newFormationPosUpNeed
        let res = playerHandle.getNeedAndUse(player, needConfig, attriPosLvl + 1)
        if (res) {
            return {
                err: res
            }
        }
        player.formation.posAttriLvl[attri] = attriPosLvl + 1
        return {
            err: 0
        }
    }

    @localApi('playerRoute')
    setPosAttri(pos, attri, gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        if (!attri) {
            delete player.formation.posAttri[pos]
            return {
                err: 0
            }
        }
        player.formation.posAttri[pos] = attri
        playerHandle.initTeam(player)
        return {
            err: 0
        }
    }
    @localApi('playerRoute')
    initEquipmentBag2(gamRouteData?: GameRouteData) {
        let { player, dayTime, time } = gamRouteData
        let vip = playerHandle.getVipLvl(player)
        let addSize = gameConfigHandle.gameConfig.vip.addBag[vip]
        player.equipmentBag2.type = BagType.Equipment2
        player.equipmentBag2.addSize = addSize + (player.baseInfo.eqBag2AddSize || 0)
        bagHandle.initPackag(player.equipmentBag2)
        return {
            err: 0
        }

    }

    @localApi('playerRoute')
    buyTownMarketItem(index: number, gamRouteData?: GameRouteData) {
        let { player, dayTime, random } = gamRouteData
        let marketItems = player.market.townMarketItems || []
        if (!marketItems || !marketItems[index]) {
            return {
                err: 5
            }
        }
        let item = marketItems[index]
        if (item.limit && item.buyTimes >= item.limit) {
            return {
                err: 6
            }
        }
        let reduceItem = {
            items: [{
                itemID: item.itemID2,
                amount: [item.amount2, 0]
            }]
        }
        let res = playerHandle.getNeedAndUse(player, reduceItem, 1)
        if (res) {
            return {
                err: res
            }
        }
        if (item.itemID1 == 'gold' || item.itemID1 == 'diamond' || item.itemID1 == 'diamond2') {
            player.itemInfo[item.itemID1] = (player.itemInfo[item.itemID1] || 0) + item.amount1
        } else if (typeof item.itemID1 == 'number') {
            bagHandle.AddItem(player.bag, item.itemID1, item.amount1, random)
        }
        item.buyTimes = (item.buyTimes || 0) + 1
        return {
            err: 0
        }
    }
}

export let playerRoute: PlayerRoute = new PlayerRoute()
// export let playerRouteBak: PlayerRoute = new PlayerRoute()